package reflect;

// 反射

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectClassDemo {
    // 通过反射来创建对象
    public static void reflectNewInstance() {
        // 首先要有Class对象
        try {
            Class<?> c1 = Class.forName("reflect.Student");

            // 创建一个学生实例
            Student student = (Student) c1.newInstance();
            // newInstance也会抛异常（所以要捕获），况且返回值是Object/T类型，所以需要强转

            // 创建好对象后进行输出
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    // 反射私有构造方法，屏蔽内容公有构造方法
    public static void reflectPrivateConstructor() {
        // 同样，首先Class对象
        try {
            Class<?> c1 = Class.forName("reflect.Student");

            // 获取所有构造方法
            // 受查异常（捕获异常）  还要注意参数（因为私有构造方法参数是String。int类型）
            // 返回类型是Constructor
            Constructor<?> constructor = c1.getDeclaredConstructor(String.class,int.class);

            // 调用之前要进行确认，毕竟是私有的
            // 只有在这里确认之后才后面调用该方法时才不回出错！
            constructor.setAccessible(true);

            // 开始进行调用（私有带参构造方法）
            // 注意返回类型+强转
            Student student = (Student) constructor.newInstance("XiaoYuan",16); // 同样捕获异常

            // 输出
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }


    // 反射私有属性
    public static void reflectPrivateField() {
        // 同样，必须有Class对象
        try {
            Class<?> c1 = Class.forName("reflect.Student");

            // 创建对象:强转+捕获异常
            Student student = (Student) c1.newInstance();

            // 获取所有属性：捕获异常 + 返回类型
           Field field = c1.getDeclaredField("name"); // 参数是私有字段

            // 获取完私有属性后进行确认是否进行修改
            field.setAccessible(true);

            // 对该属性进行修改
            field.set(student,"懒羊羊"); // 参数是对象，新的属性值

            System.out.println(student);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }



    // 反射私有方法
    public static void reflectPrivateMethod() {
        // 同样，Class对象
        try {
            Class<?> c1 = Class.forName("reflect.Student");

            // 创建对象
            Student student = (Student) c1.newInstance();

            // 获取私有方法:注意异常+返回值
            Method method = c1.getDeclaredMethod("function", String.class); // 参数是：（方法名，方法的参数类型）

            // 获取私有方法后进行确认
            method.setAccessible(true);

            // 进行修改传参
            method.invoke(student,"我是通过反射进行传参的");

//            // 打印：不需要，因为是调用私有方法，已经直接再该方法中进行打印了
//            System.out.println(student);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }



    public static void main(String[] args) {
        // 调用方法：
        reflectNewInstance();
        reflectPrivateConstructor();
        reflectPrivateField();
        reflectPrivateMethod();

    }
}
